home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / TEX-UTIL / DVIPS_55 / dvips / src / c / loadfont < prev    next >
Text File  |  1994-05-06  |  14KB  |  472 lines

  1. /*
  2.  *   Here's the code to load a PK file into memory.
  3.  *   Individual bitmaps won't be unpacked until they prove to be needed.
  4.  */
  5. #include "dvips.h" /* The copyright notice in that file is included too! */
  6.  
  7. #ifdef OS2
  8. #include <stdlib.h>
  9. #endif
  10. /*
  11.  *   These are the external routines we use.
  12.  */
  13. extern void makefont() ;
  14. extern void error() ;
  15. extern integer scalewidth() ;
  16. extern int tfmload() ;
  17. extern FILE *pksearch() ;
  18. /*
  19.  *   These are the external variables we use.
  20.  */
  21. #ifdef DEBUG
  22. extern integer debug_flag;
  23. #endif  /* DEBUG */
  24. extern long bytesleft ;
  25. extern quarterword *raster ;
  26. extern real conv ;
  27. extern int actualdpi, vactualdpi ;
  28. extern real alpha ;
  29. /* extern char *pkpath ;*/
  30. char errbuf[200] ;
  31. int lastresortsizes[40] ;
  32. extern integer fsizetol ;
  33. extern Boolean nosmallchars ;
  34. extern Boolean compressed ;
  35. extern Boolean dopprescan ;
  36. #ifdef FONTLIB
  37. extern Boolean flib ;
  38. extern FILE *flisearch() ;
  39. #endif
  40. /*
  41.  *   Now we have some routines to get stuff from the PK file.
  42.  *   Subroutine pkbyte returns the next byte.
  43.  */
  44. FILE *pkfile ;
  45. char name[50] ;
  46. void
  47. badpk(s)
  48.    char *s ;
  49. {
  50.    sprintf(errbuf,"! Bad PK file %s: %s",name,s) ;
  51.    error(errbuf);
  52. }
  53.  
  54. shalfword
  55. pkbyte()
  56. {
  57.    register shalfword i ;
  58.  
  59.    if ((i=getc(pkfile))==EOF)
  60.       badpk("unexpected eof") ;
  61.   
  62.    return(i) ;
  63. }
  64.  
  65. integer
  66. pkquad()
  67. {
  68.    register integer i ;
  69.  
  70.    i = pkbyte() ;
  71.    if (i > 127)
  72.       i -= 256 ;
  73.    i = i * 256 + pkbyte() ;
  74.    i = i * 256 + pkbyte() ;
  75.    i = i * 256 + pkbyte() ;
  76.    return(i) ;
  77. }
  78.  
  79. integer
  80. pktrio()
  81. {
  82.    register integer i ;
  83.  
  84.    i = pkbyte() ;
  85.    i = i * 256 + pkbyte() ;
  86.    i = i * 256 + pkbyte() ;
  87.    return(i) ;
  88. }
  89.  
  90.  
  91. /*
  92.  *   pkopen opens the pk file.  This is system dependent.  We work really
  93.  *   hard to open some sort of PK file.
  94.  */
  95. #ifdef VMCMS /* IBM: VM/CMS - we let DVIPS EXEC handle this after
  96.                              the DVIPS MODULE has finished to avoid
  97.                              complications with system calls. */
  98. int dontmakefont = 0 ;
  99. #else
  100. #ifdef MVSXA /* IBM: MVS/XA - we let system administrator handle this on
  101.                             MVS/XA since some printers can't get to user
  102.                              fonts anyway */
  103. int dontmakefont = 1 ;
  104. #else
  105. int dontmakefont = 0 ; /* if makefont fails once we won't try again */
  106. #endif  /* IBM: VM/CMS */
  107. #endif
  108.  
  109. void
  110. lectureuser() {
  111.    static int userwarned = 0 ;
  112.  
  113.    if (! userwarned) {
  114.       error("Such scaling will generate extremely poor output.") ;
  115.       userwarned = 1 ;
  116.    }
  117. }
  118. Boolean
  119. pkopen(fd)
  120.         register fontdesctype *fd ;
  121. {
  122.    register char *d, *n ;
  123.    int vdpi ;
  124.  
  125.    d = fd->area ;
  126.    n = fd->name ;
  127.    if (*d==0)
  128.       d = pkpath ;
  129. #ifdef FONTLIB
  130.    if (*(fd->area) == 0) {
  131.       int del ;
  132.       for (del=0; del<=RES_TOLERANCE(fd->dpi); del=del>0?-del:-del+1) {
  133.         if ((pkfile=flisearch(n, fd->dpi + del)) != (FILE *)NULL )
  134.           return(1);
  135.       }
  136.    }
  137. #endif
  138.    {
  139.       int del ;
  140.       for (del=0; del<=RES_TOLERANCE(fd->dpi); del=del>0?-del:-del+1) {
  141.          if (actualdpi == vactualdpi) {
  142.             vdpi = 0 ;
  143.          } else {
  144.             vdpi = (2 * ((long)vactualdpi) * (fd->dpi + del) + actualdpi)
  145.                                                        / (2 * actualdpi) ;
  146.          }
  147. #ifdef MVSXA
  148.          sprintf(name, "pk%d(%s)", fd->dpi + del, n) ;
  149. #else
  150.          sprintf(name, "%s.%dpk", n, fd->dpi + del) ;
  151. #endif
  152.          if (0 != (pkfile=pksearch(d, name, READBIN, n, fd->dpi + del, vdpi)))
  153.             return(1) ;
  154.       }
  155.    }
  156.    if (d == pkpath) {
  157.       if (actualdpi == vactualdpi) {
  158.          vdpi = 0 ;
  159.       } else {
  160.          vdpi = (2 * ((long)vactualdpi) * fd->dpi + actualdpi)
  161.                                                     / (2 * actualdpi) ;
  162.       }
  163. #ifdef MVSXA
  164.       sprintf(name, "pk%d(%s)", fd->dpi, n) ;
  165. #else
  166.       sprintf(name, "%s.%dpk", n, fd->dpi) ;
  167. #endif
  168.       makefont(n, (int)fd->dpi, DPI) ;
  169.       if (dontmakefont == 0 &&
  170.           (pkfile = pksearch(d, name, READBIN, n, fd->dpi, vdpi)))
  171.                return(1) ;
  172. #ifndef MSDOS
  173. #ifdef OS2
  174.    if (_osmode == OS2_MODE)
  175.       dontmakefont = 1;       /* failed so don't try again under OS/2, 
  176.                                  but do try for MSDOS */
  177. #else
  178.       dontmakefont = 1 ;
  179. #endif
  180. #endif
  181.    }
  182. /*
  183.  *   If nothing above worked, then we get desparate.  We attempt to
  184.  *   open the stupid font at one of a small set of predefined sizes,
  185.  *   and then use PostScript scaling to generate the correct size.
  186.  *
  187.  *   We much prefer scaling up to scaling down, since scaling down
  188.  *   can omit character features, so we try the larger sizes first,
  189.  *   and then work down.
  190.  */
  191.    {
  192.       int i, j ;
  193.  
  194.       if (lastresortsizes[0] && fd->dpi < 30000) {
  195.          for (i=0; lastresortsizes[i] < fd->dpi; i++) ;
  196.          for (j = i-1; j >= 0; j--) {
  197.             if (actualdpi == vactualdpi) {
  198.                vdpi = 0 ;
  199.             } else {
  200.                vdpi = (2 * ((long)vactualdpi) * lastresortsizes[j] + actualdpi)
  201.                                                        / (2 * actualdpi) ;
  202.             }
  203. #ifdef MVSXA
  204.             sprintf(name, "pk%d(%s)", lastresortsizes[j], n) ;
  205. #else
  206.             sprintf(name, "%s.%dpk", n, lastresortsizes[j]) ;
  207. #endif
  208. #ifdef FONTLIB
  209.             if (0 != (pkfile=flisearch(n,(halfword)lastresortsizes[j]))
  210.              || 0 != (pkfile=pksearch(d, name, READBIN, n,
  211.                          (halfword)lastresortsizes[j], vdpi))) {
  212. #else
  213.             if (0 != (pkfile=pksearch(d, name, READBIN, n,
  214.                          (halfword)lastresortsizes[j], vdpi))) {
  215. #endif
  216.                fd->loadeddpi = lastresortsizes[j] ;
  217.                fd->alreadyscaled = 0 ;
  218.                sprintf(errbuf,
  219.                        "Font %s at %d not found; scaling %d instead.",
  220.                                          name, fd->dpi, lastresortsizes[j]) ;
  221.                error(errbuf) ;
  222.                lectureuser() ;
  223.                return 1 ;
  224.             }
  225.          }
  226.          for (j = i; lastresortsizes[j] < 30000; j++) {
  227.             if (actualdpi == vactualdpi) {
  228.                vdpi = 0 ;
  229.             } else {
  230.                vdpi = (2 * ((long)vactualdpi) * lastresortsizes[j] + actualdpi)
  231.                                                        / (2 * actualdpi) ;
  232.             }
  233.             sprintf(name, "%s.%dpk", n, lastresortsizes[j]) ;
  234. #ifdef FONTLIB
  235.             if (0 != (pkfile=flisearch(n, (halfword)lastresortsizes[j]))
  236.                 || 0 != (pkfile=pksearch(d, name, READBIN, n,
  237.                              (halfword)lastresortsizes[j], vdpi))) {
  238. #else
  239.             if (0 != (pkfile=pksearch(d, name, READBIN, n,
  240.                             (halfword)lastresortsizes[j], vdpi))) {
  241. #endif
  242.                fd->loadeddpi = lastresortsizes[j] ;
  243.                fd->alreadyscaled = 0 ;
  244.                sprintf(errbuf,
  245.                        "Font %s at %d not found; scaling %d instead.",
  246.                                          name, fd->dpi, lastresortsizes[j]) ;
  247.                error(errbuf) ;
  248.                lectureuser() ;
  249.                return 1 ;
  250.             }
  251.          }
  252.       }
  253.    }
  254. #ifdef MVSXA
  255.    sprintf(name, "%s.pk%d", n, fd->dpi) ;
  256. #else
  257.    sprintf(name, "%s.%dpk", n, fd->dpi) ;
  258. #endif
  259.    sprintf(errbuf,
  260.       "Font %s%s not found, characters will be left blank.",
  261.       fd->area, name) ;
  262.    error(errbuf) ;
  263.    return(0) ;
  264. }
  265.  
  266. /*
  267.  *   Now our loadfont routine.  We return an integer indicating the
  268.  *   highest character code in the font, so we know how much space
  269.  *   to reserve for the character.  (It's returned in the font
  270.  *   structure, along with everything else.)
  271.  */
  272. void
  273. loadfont(curfnt)
  274.         register fontdesctype *curfnt ;
  275. {
  276.    register shalfword i ;
  277.    register shalfword cmd ;
  278.    register integer k ;
  279.    register integer length = 0 ;
  280.    register shalfword cc = 0 ;
  281.    register integer scaledsize = curfnt->scaledsize ;
  282.    register quarterword *tempr ;
  283.    register chardesctype *cd = 0 ;
  284.    int maxcc = 0 ;
  285.    int munged = 0 ;
  286. /*
  287.  *   We clear out some pointers:
  288.  */
  289.    if (curfnt->loaded == 3) {
  290.       for (i=0; i<256; i++) {
  291.          curfnt->chardesc[i].TFMwidth = 0 ;
  292.          curfnt->chardesc[i].packptr = NULL ;
  293.          curfnt->chardesc[i].pixelwidth = 0 ;
  294.          curfnt->chardesc[i].flags &= EXISTS ;
  295.       }
  296.    } else {
  297.       for (i=0; i<256; i++) {
  298.          curfnt->chardesc[i].TFMwidth = 0 ;
  299.          curfnt->chardesc[i].packptr = NULL ;
  300.          curfnt->chardesc[i].pixelwidth = 0 ;
  301.          curfnt->chardesc[i].flags = 0 ;
  302.       }
  303.    }
  304.    curfnt->maxchars = 256 ; /* just in case we return before the end */
  305.    if (!pkopen(curfnt)) {
  306.       tfmload(curfnt) ;
  307.       return ;
  308.    }
  309. #ifdef DEBUG
  310.    if (dd(D_FONTS))
  311.       (void)fprintf(stderr,"Loading pk font %s at %.1fpt\n",
  312.          name, (real)scaledsize/(alpha*0x100000)) ;
  313. #endif /* DEBUG */
  314.    if (pkbyte()!=247)
  315.       badpk("expected pre") ;
  316.    if (pkbyte()!=89)
  317.       badpk("wrong id byte") ;
  318.    for(i=pkbyte(); i>0; i--)
  319.       (void)pkbyte() ;
  320.    k = (integer)(alpha * (real)pkquad()) ;
  321.    if (k > curfnt->designsize + fsizetol ||
  322.        k < curfnt->designsize - fsizetol) {
  323.       sprintf(errbuf,"Design size mismatch in font %s", name) ;
  324.       error(errbuf) ;
  325.    }
  326.    k = pkquad() ;
  327.    if (k && curfnt->checksum)
  328.       if (k!=curfnt->checksum) {
  329.          sprintf(errbuf,"Checksum mismatch in font %s", name) ;
  330.          error(errbuf) ;
  331.        }
  332.    k = pkquad() ; /* assume that hppp is correct in the PK file */
  333.    k = pkquad() ; /* assume that vppp is correct in the PK file */
  334. /*
  335.  *   Now we get down to the serious business of reading character definitions.
  336.  */
  337.    while ((cmd=pkbyte())!=245) {
  338.       if (cmd < 240) {
  339.          switch (cmd & 7) {
  340. case 0: case 1: case 2: case 3:
  341.             length = (cmd & 7) * 256 + pkbyte() - 3 ;
  342.             cc = pkbyte() ;
  343.             cd = curfnt->chardesc+cc ;
  344.             if (nosmallchars || curfnt->dpi != curfnt->loadeddpi)
  345.                cd->flags |= BIGCHAR ;
  346.             cd->TFMwidth = scalewidth(pktrio(), scaledsize) ;
  347.             cd->pixelwidth = pkbyte() ;
  348.             break ;
  349. case 4: case 5: case 6:
  350.             length = (cmd & 3) * 65536L + pkbyte() * 256L ;
  351.             length = length + pkbyte() - 4L ;
  352.             cc = pkbyte() ;
  353.             cd = curfnt->chardesc+cc ;
  354.             cd->TFMwidth = scalewidth(pktrio(), scaledsize) ;
  355.             cd->flags |= BIGCHAR ;
  356.             i = pkbyte() ;
  357.             cd->pixelwidth = i * 256 + pkbyte() ;
  358.             break ;
  359. case 7:
  360.             length = pkquad() - 11 ;
  361.             cc = pkquad() ;
  362.             if (cc<0 || cc>255) badpk("character code out of range") ;
  363.             cd = curfnt->chardesc + cc ;
  364.             cd->flags |= BIGCHAR ;
  365.             cd->TFMwidth = scalewidth(pkquad(), scaledsize) ;
  366.             cd->pixelwidth = (pkquad() + 32768) >> 16 ;
  367.             k = pkquad() ;
  368.          }
  369.          if (cd->pixelwidth == 0 && cd->TFMwidth != 0) {
  370.             if (cd->TFMwidth > 0)
  371.                k = (integer)(cd->TFMwidth * conv + 0.5) ;
  372.             else
  373.                k = -(integer)(-cd->TFMwidth * conv + 0.5) ;
  374.             if (k != 0) {
  375.                cd->pixelwidth = k ;
  376.                munged++ ;
  377.             }
  378.          }
  379.          if (length <= 0)
  380.             badpk("packet length too small") ;
  381.          if (dopprescan && ((cd->flags & EXISTS) == 0)) {
  382.             for (length--; length>0; length--)
  383.                (void)pkbyte() ;
  384.          } else {
  385.             if (cc > maxcc)
  386.                maxcc = cc ;
  387.             if (bytesleft < length || (length > MINCHUNK && compressed)) {
  388. #ifdef DEBUG
  389.                 if (dd(D_FONTS))
  390.                    (void)fprintf(stderr,
  391. #ifdef SHORTINT
  392.                       "Allocating new raster memory (%ld req, %ld left)\n",
  393.                                    length, bytesleft) ;
  394. #else
  395.                       "Allocating new raster memory (%d req, %d left)\n",
  396.                                    (int)length, (int)bytesleft) ;
  397. #endif
  398. #endif /* DEBUG */
  399.                 if (length > MINCHUNK) {
  400.                    tempr = (quarterword *)mymalloc((integer)length) ;
  401.                 } else {
  402.                    raster = (quarterword *)mymalloc((integer)RASTERCHUNK) ;
  403.                    tempr = raster ;
  404.                    bytesleft = RASTERCHUNK - length ;
  405.                    raster += length ;
  406.                }
  407.             } else {
  408.                tempr = raster ;
  409.                bytesleft -= length ;
  410.                raster += length ;
  411.             }
  412.             cd->packptr = tempr ;
  413.             *tempr++ = cmd ;
  414.             for (length--; length>0; length--)
  415.                *tempr++ = pkbyte() ;
  416.          }
  417.       } else {
  418.          k = 0 ;
  419.          switch (cmd) {
  420. case 243:
  421.             k = pkbyte() ;
  422.             if (k > 127)
  423.                k -= 256 ;
  424. case 242:
  425.             k = k * 256 + pkbyte() ;
  426. case 241:
  427.             k = k * 256 + pkbyte() ;
  428. case 240:
  429.             k = k * 256 + pkbyte() ;
  430.             while (k-- > 0)
  431.                i = pkbyte() ;
  432.             break ;
  433. case 244:
  434.             k = pkquad() ;
  435.             break ;
  436. case 246:
  437.             break ;
  438. default:
  439.             badpk("! unexpected command") ;
  440.          }
  441.       }
  442.    }
  443. #ifdef FONTLIB
  444.    if (flib)
  445.       flib = 0 ;
  446.    else
  447. #endif
  448.    (void)fclose(pkfile) ;
  449.    curfnt->loaded = 1 ;
  450.    curfnt->maxchars = maxcc + 1 ;
  451.    if (munged > 0) {
  452.       static int seen = 0 ;
  453.       sprintf(errbuf,
  454.           "Font %s at %d dpi has most likely been made improperly;",
  455.            curfnt->name, curfnt->dpi) ;
  456.       error(errbuf) ;
  457.       if (seen)
  458.          return ;
  459.       seen = 1 ;
  460.       sprintf(errbuf,
  461.      "%d characters have 0 escapements but non-trivial TFM widths.", munged) ;
  462.       error(errbuf) ;
  463.       error(
  464.           "I'm stumbling along as best I can, but I recommend regenerating") ;
  465.       error(
  466.           "these fonts; the problem is probably that they are non-CM fonts") ;
  467.       error(
  468.           "(such as circle10 or line10) created with a MF with the CM base") ;
  469.       error("preloaded .") ;
  470.    }
  471. }
  472.